import dayjs from "dayjs";
import { useMemo, RefObject, cloneElement, useCallback, useEffect, useRef, useState } from "react";

export type TDate = dayjs.ConfigType

export interface Options {
  leftTime?: number
  targetDate?: TDate
  interval?: number
  onEnd?: () => void
}

export interface FormattedRes {
  days: number
  hours: number
  minutes: number
  seconds: number
  milliseconds: number
}

const calcLeft = (target?: TDate) => {
  if (!target) {
    return 0
  }
  const left = dayjs(target).valueOf() - Date.now()
  return left < 0 ? 0 : left
}

const parseMs = (milliseconds: number): FormattedRes => {
  return {
    days: Math.floor(milliseconds / 86400000),
    hours: Math.floor(milliseconds / 3600000) % 24,
    minutes: Math.floor(milliseconds / 60000) % 60,
    seconds: Math.floor(milliseconds / 1000) % 60,
    milliseconds: Math.floor(milliseconds) % 1000
  }
}

export default function useCountDown(options: Options = {}){
  const { leftTime, targetDate, interval = 1000, onEnd } = options || {};

  const memoLeftTime = useMemo(() => {
    return leftTime && leftTime > 0 ? Date.now() + leftTime : undefined
  }, [leftTime])

  const target = 'leftTime' in options ? memoLeftTime : targetDate

  const [timeLeft, setTimeLeft] = useState(() => calcLeft(target));
  const onEndRef = useRef(onEnd)
  onEndRef.current = onEnd;
  useEffect(() => {
    if (!target) {
      setTimeLeft(0)
      return
    }
    setTimeLeft(calcLeft(target))
    const timer = setInterval(() => {
      const targetLeft = calcLeft(target)
      setTimeLeft(targetLeft)
      if (targetLeft === 0) {
        clearInterval(timer)
        onEndRef.current?.()
      }
    }, interval)
    return () => clearInterval(timer)
  }, [target, interval]);

  const formattedRes = useMemo(() => parseMs(timeLeft), [timeLeft])
  return [timeLeft, formattedRes] as const
}